package serveur;

import java.io.IOException;
import java.net.ServerSocket;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.Date;

import client.*;
import bdd.ConnexionBDD;

/**
 * Classe Serveur 
 *
 */
public class Serveur 
{	
	// nombre total de clients connectés
	private int _nbClients=0; 
	//tableau des email des utilisateurs connectés
	private ArrayList<Client> clients=new ArrayList<Client>();
	ConnexionBDD conn;
	private String demandeur=null;	

	/** Constructeur **/
	public Serveur()
	{
	
	}//fin Serveur()
	  
	  
	/** Methode : la première méthode exécutée, elle attend les connexions **/
	public void seConnecter() throws IOException
	{
	    Integer port=new Integer(18888);
	    ServerSocket ss = new ServerSocket(port);
		System.out.println("le serveur est pret");
		while (true) // attente en boucle de connexion (bloquant sur ss.accept)
		{
			new ThreadClient(ss.accept(),this); // un client se connecte, un nouveau thread client est lancé
	    }
	}//fin seConnecter()


	/** Methode : envoie le message à un seul client **/
	synchronized public void envoieClient(String message,String mailR,String mailE)
	{
		String mess="";
		// declaration d'une variable permettant l'envoi de texte vers le client
		//PrintWriter out;
		for (int i = 0; i < clients.size(); i++) // parcours de la table des connectés
		{
			if(clients.get(i).getEmail().compareTo(mailR)==0)
			{
				mess="M"+mailE+";"+message+"\u0000";
				clients.get(i).getOut().write(mess);
				clients.get(i).getOut().flush();
			}
	    }
	}//fin sendAll()
	  

	  /** Methode : Verifie la connexion **/
	  synchronized public int verifConnection(String identifiant,String motDePasse) throws SQLException
	  {
		//connexion à la base de donnée pour vérifier les identifiants
		ConnexionBDD conn2=new ConnexionBDD();
		conn2.seConnecter();
		String requete="select * from Utilisateur;";		
		conn2.setRs(conn2.getStmt().executeQuery(requete));		
		while(conn2.getRs().next())
		{
			if(conn2.getRs().getString("email").compareTo(identifiant)==0)
			{
				if(conn2.getRs().getString("mot_de_passe").compareTo(motDePasse)==0)
				{
					//lancement de la connection sur le serveur
					conn2.seDeconnecter();
					return 1;
				}
			}
		}
		conn2.seDeconnecter();
		return 0;
	  }//fin verifConnexion()


	  /** Methode : détruit le client no i **/
	  synchronized public void delClient(String mail)
	  {
	    _nbClients--; // un client en moins ! snif
	    int i=0;
	    if(clients.size()!=0)
	    {
	    	while(clients.size()>i)
	    	{
	    		if(clients.get(i).getEmail().compareTo(mail)==0){
	    			clients.remove(i);
	    			break;
	    		}
	    		i++;
	    	}
	    }
	  }//fin delClient()


	  /** Methode : ajoute un nouveau client dans la liste **/
	  synchronized public void addClient(Client cl)
	  {
	    _nbClients++; 
	    clients.add(cl); // on ajoute le nouveau flux de sortie au tableau
	  }//fin addClient()
	  
	  
	  /** Methode : affiche la liste des clients connectés **/
	  synchronized public void afficheClients()
	  {
		  int i=0;
		  while(i!=clients.size())
		  {
			  i++;
		  }
	  }//fin afficheClients()
	  

	  /** Methode : retourne la liste d'amis d'un client
	   * si connect=true retourne la liste des connectés sinon la liste des déconnectés**/
	  synchronized public ArrayList<Client> listeAmisClientsC(String email,boolean connect) throws SQLException
	  {
		  ArrayList<Client> listeAmis =new ArrayList<Client>();
		  ConnexionBDD conn= new ConnexionBDD();
		  conn.seConnecter();
		  int i=0;
		  String requete="select * from Contient where email='"+email+"'";
		  conn.setRs(conn.getStmt().executeQuery(requete));
		  String mailAmi;
		  boolean ajout=false;
		  while(conn.getRs().next()){
			  i=0;
			  ajout=false;
			  mailAmi=conn.getRs().getString("email_ami");
			  while(i!=clients.size()){				 
					  if(clients.get(i).getEmail().compareTo(mailAmi)==0)
					  {		
						  if(connect==true){
						  listeAmis.add(clients.get(i));
						  }
						  ajout=true;
					  }			  
					  i++;
			  }
			  if(connect==false){
				  if(ajout==false){
					  listeAmis.add(new Client(null,mailAmi,"","", "", "", ""));
				  }
			  }
		  }
		  conn.seDeconnecter();

		  return listeAmis;
	  }//fin ListeAmisClients()
	  
	  
	  /** Methode : actualise la liste d'amis des clients lorsque email se connecte ou se déconnecte
	   * bool =true si email se connecte et false si il se déconnecte**/
	  synchronized public void ActualiseListeAmis(String clMail,boolean connect) throws SQLException
	  {
		  ConnexionBDD conn= new ConnexionBDD();
		  conn.seConnecter();
		  int i=0;
		  String requete="select * from Contient where email='"+clMail+"'";
		  conn.setRs(conn.getStmt().executeQuery(requete));
		  String mailAmi;
		  String mess="";
		  while(conn.getRs().next())
		  {
			  mailAmi=conn.getRs().getString("email_ami");
			  i=0;
			  while(i<clients.size())
			  {
				  if(clients.get(i).getEmail().compareTo(mailAmi)==0)
				  {	  
					  if(connect==true)
						  mess="A"+"c"+clMail+";"+clients.get(i).getStatut()+";"+clients.get(i).getPseudo();
					  else
						  mess="A"+"d"+clMail;
					  clients.get(i).getOut().print(mess+"\u0000");
					  clients.get(i).getOut().flush();
				  }
				  i++;
			  }
		  }
	  }// fin ActualiseListeAmis()

	  
	  /** Methode : actualise la liste d'amis des clients lorsque email se connecte ou se déconnecte
	   * bool =true si email se connecte et false si il se déconnecte**/
	  synchronized public void actualiseStatuts(String clMail,String statut) throws SQLException
	  {
		  ConnexionBDD conn= new ConnexionBDD();
		  conn.seConnecter();
		  int i=0;
		  String requete="select * from Contient where email='"+clMail+"'";
		  conn.setRs(conn.getStmt().executeQuery(requete));
		  String mailAmi;
		  String mess="";
		  while(conn.getRs().next())
		  {
			  mailAmi=conn.getRs().getString("email_ami");
			  i=0;
			  while(i<clients.size())
			  {
				  if(clients.get(i).getEmail().compareTo(mailAmi)==0){	  
					  mess="T"+clMail+";"+statut+"\u0000";
					  System.out.println(mess);
					  clients.get(i).getOut().write(mess);
					  clients.get(i).getOut().flush();
				  }
				  if(clients.get(i).getEmail().compareTo(clMail)==0){
					  clients.get(i).setStatut(statut);
				  }	
				  i++;
			  }
		  }
	  }// fin ActualiseListeAmis()
	  
	  /** Methode : actualise la liste d'amis des clients lorsque email se connecte ou se déconnecte
	   * bool =true si email se connecte et false si il se déconnecte**/
	  synchronized public void actualisePseudos(String clMail,String pseudo) throws SQLException
	  {
		  ConnexionBDD conn= new ConnexionBDD();
		  conn.seConnecter();
		  int i=0;
		  String requete="select * from Contient where email='"+clMail+"'";
		  conn.setRs(conn.getStmt().executeQuery(requete));
		  String mailAmi;
		  String mess="";
		  while(conn.getRs().next())
		  {
			  mailAmi=conn.getRs().getString("email_ami");
			  i=0;
			  while(i<clients.size())
			  {
				  if(clients.get(i).getEmail().compareTo(mailAmi)==0)
				  {	  
					  mess="P"+clMail+";"+pseudo+"\u0000";
					  System.out.println(mess);
					  clients.get(i).getOut().write(mess);
					  clients.get(i).getOut().flush();
				  }
				  if(clients.get(i).getEmail().compareTo(clMail)==0){
					  clients.get(i).setPseudo(pseudo);
				  }	
				  i++;
			  }
		  }
	  }// fin ActualiseListeAmis()
	  
	  
	  
	  
	  /** Methode : retourne le nombre de clients connectés **/
	  synchronized public int getNbClients()
	  {
	    return _nbClients; // retourne le nombre de clients connectés
	  }//fin getNbClients()
	  
	  
	  /** Methode : verifie que l'email n'existe pas déja ds la BDD 
	   * initialisee a 2 puis 0 si existe deja, 1 sinon **/
	  synchronized public int verifEmailExistePas(Client cl)
	  {
		ConnexionBDD conn = new ConnexionBDD();
		conn.seConnecter();
		String requete="select count(*) from Utilisateur where email='"+cl.getEmail()+"';";
		int req=2;
		try 
		{
			conn.setRs(conn.getStmt().executeQuery(requete));
		
			while(conn.getRs().next()){
				if(conn.getRs().getString("count(*)").compareTo("0")==0){
						req=1;//l'adresse n'existe pas encore : super
				}
				else req=0;
			}
		} catch (SQLException e) {e.printStackTrace();}
		return req;
	  }//fin verifEmailExistePas()
	  
	  
	  /** Methode : inscrit le client ds la BDD **/
	  synchronized public int inscrireClient(Client cl)
	  {
		  ConnexionBDD conn3 = new ConnexionBDD();
		  int req=0;
		  conn3.seConnecter();
		  String SQL = "insert into Utilisateur values ('" + cl.getEmail() + "','"+ 
		  cl.getNom()+"','" + cl.getPrenom()+"','"+ cl.getMdp() + "',1)";
		  try 
		  {
			conn3.getStmt().executeUpdate(SQL);
			req=1;
		  } 
		  catch (SQLException e) 
		  {
			  e.printStackTrace();
		  }		
		  conn3.seDeconnecter();
		  return req; 				
	  }//fin inscrireClient()

	  
	  /** Methode : verifie si la demande d'ami correspond a une adresse de la BDD 
	   * et s'ils ne sont pas déjà amis 
	   * req=req1+req2**/
	  synchronized public String verifAdrExiste(String email, String dem)
	  {
		ConnexionBDD conn = new ConnexionBDD();
		conn.seConnecter();// conn???
		String requete="select count(*) from Utilisateur where email='"+dem+"' and email!='"+email+"';";
		String req, req1, req2, req3;
		req="2";req1="2";req2="2";req3="2";
		try 
		{
			conn.setRs(conn.getStmt().executeQuery(requete));
		
			while(conn.getRs().next()){
				if(conn.getRs().getString("count(*)").compareTo("1")==0){
						req1="1";//l'adresse existe : super
				}
				else req1="0";
			}
		} catch (SQLException e) {e.printStackTrace();}
		String requete2="select count(*) from Contient where (email='"+email+"' and email_ami='"+dem+"')" +
				" or (email='"+dem+"' and email_ami='"+email+"') ;";
		
		try 
		{
			conn.setRs(conn.getStmt().executeQuery(requete2));
		
			while(conn.getRs().next()){
				if(conn.getRs().getString("count(*)").compareTo("0")==0){
						req2="1";//ils ne sont pas deja amis : super
				}
				else req2="0";
			}
		} catch (SQLException e) {e.printStackTrace();}
		String requete3="select count(*) from Demande where (email_demandeur='"+email+"' and email_receveur='"+dem+"');";
		try {
			conn.setRs(conn.getStmt().executeQuery(requete3));
		
			while(conn.getRs().next()){
				if(conn.getRs().getString("count(*)").compareTo("0")==0)
				{
						req3="1";//il n'a pas deja fait la demande : Super
				}
				else req3="0";
			}
		} catch (SQLException e) {e.printStackTrace();}
		req=req1+req2+req3;
		conn.seDeconnecter();
		return req;// le mieux req=111;
	  }//fin verifAdrExiste()
	  
	  
	  /** Methode : enregistre la demande dans la BDD **/
	  synchronized public int enregistrerDemande(String email_demandeur, String email_receveur)
	  {
		  int req=0;
		 ConnexionBDD conn = new ConnexionBDD();
		  conn.seConnecter();
		  String SQL = "insert into Demande values ('" + email_demandeur + "','"+ email_receveur+"');";
		  try 
		  {
			conn.getStmt().executeUpdate(SQL);
			req=1;
		  } 
		  catch (SQLException e) 
		  {
			  e.printStackTrace();
			  System.out.println("Erreur lors de l enregistrement de la demande dans la BDD");
		  }		
		  conn.seDeconnecter();
		  return req; 				
	  }//fin enregistrerDemande()
	  
	  

	  /** Methode : verifie s'il y a des demandes **/
	  synchronized public int verifierDemande(String email)
	  {
		  int req=2;
		  ConnexionBDD conn = new ConnexionBDD();
		  conn.seConnecter();
		  String requete="select count(*) from Demande where email_receveur='"+email+"';";
			try {
				conn.setRs(conn.getStmt().executeQuery(requete));
				while(conn.getRs().next()){
					if(conn.getRs().getString("count(*)").compareTo("0")==0){
							req=0;
					}
					else req=1;						
				}
			} catch (SQLException e) {e.printStackTrace();}	
		  conn.seDeconnecter(); 
		  return req; 				
	  }//fin verifierDemande()
	  
	  
	  /** Methode : affiche s'il y a des demandes **/
	  synchronized public String afficherDemande(String email){
		  ConnexionBDD conn = new ConnexionBDD();
		  conn.seConnecter();
		  String requete="select email_demandeur from Demande where email_receveur='"+email+"' limit 1;";
		  try {
				conn.setRs(conn.getStmt().executeQuery(requete));			
				conn.getRs().next();
				demandeur=conn.getRs().getString("email_demandeur");				
			} catch (SQLException e) {e.printStackTrace();}	
		  conn.seDeconnecter();	
		  return demandeur;
	  }//fin afficherDemande()
	  
	  
	  /** Methode : accepte la demande **/
	  synchronized public int accepterDemande(String email_demandeur, String email_receveur){
		  int req=0;
		  ConnexionBDD conn = new ConnexionBDD();
		  conn.seConnecter();
		  String SQL = "insert into Contient values ('" + email_demandeur + "','"+ email_receveur+"');";
		  String SQL2 = "insert into Contient values ('" + email_receveur + "','"+ email_demandeur+"');";
		 // String SQL3 = "delete from Demande where email_demandeur='" + email_demandeur + "' and email_receveur='"+ email_receveur+"';";
		  try {
			conn.getStmt().executeUpdate(SQL);
			conn.getStmt().executeUpdate(SQL2);
			req=1;
		  } 
		  catch (SQLException e) {
			  e.printStackTrace();
		  }		
		  conn.seDeconnecter();
		  return req; 				
	  }//fin accepterDemande()	  
	  
	  
	 /** Methode :supprime la demande lors du choix du receveur**/
	  synchronized public int supprimerDemande(String demandeur,String _mail){
		  int req=0;
		  ConnexionBDD conn3 = new ConnexionBDD();
		  conn3.seConnecter();
		  String SQL = "delete from Demande where (email_demandeur='"+demandeur+"' and email_receveur='"+_mail+"');";
		  try {
			conn3.getStmt().executeUpdate(SQL);
			req=1;
		  } 
		  catch (SQLException e) {
			  e.printStackTrace();
		  }		
		  conn3.seDeconnecter();
		  return req;
	  }//fin supprimerDemande 
	    
	  /** Methode :supprime l'ami**/
	  synchronized public void supprimeMess(String message){
		  ConnexionBDD conn3 = new ConnexionBDD();
		  conn3.seConnecter();
		  String SQL = "delete from Message where message='"+message+"'";
		  try {
			conn3.getStmt().executeUpdate(SQL);
		  } 
		  catch (SQLException e) 
		  {
			  e.printStackTrace();
		  }		
		  conn3.seDeconnecter();

	  }//fin supprimerAmi   
	  /** Methode :supprime l'ami**/
	  synchronized public int supprimerAmi(String mail,String mailAmi){
		  int req=0;
		  ConnexionBDD conn3 = new ConnexionBDD();
		  conn3.seConnecter();
		  String SQL = "delete from Contient where (email='"+mail+"' and email_ami='"+mailAmi+"')" +
		  		"or (email='"+mailAmi+"' and email_ami='"+mail+"');";
		  try {
			conn3.getStmt().executeUpdate(SQL);
			req=1;
		  } 
		  catch (SQLException e) {
			  e.printStackTrace();
		  }		
		  conn3.seDeconnecter();
		  return req;
	  }//fin supprimerAmi 
	  
	  synchronized public void enregistreMessage(String email_expediteur,String email_receveur,String message){
		  ConnexionBDD conn4=new ConnexionBDD();
		  conn4.seConnecter();
		  Date date=new Date();
		  String dateS=date.toString();
		  String SQL="insert into Message values('"+email_expediteur+"','"+email_receveur+"','"+
		  message+"','"+dateS+"')";
		  try {
			conn4.getStmt().executeUpdate(SQL);
		} catch (SQLException e) {
			e.printStackTrace();
		}
	  }
	  
	  synchronized ArrayList<String> recupereListeMessages(String email){
		  String message="",mail_expediteur="",date="";
		  ArrayList<String> messages=new ArrayList<String>();
		  ConnexionBDD conn5=new ConnexionBDD();
		  conn5.seConnecter();		  
		  String requete="select * from Message where email_receveur='"+email+"'";
		  try {
			  conn5.setRs(conn5.getStmt().executeQuery(requete));
			while(conn5.getRs().next()){
				message=conn5.getRs().getString("message");
				date=conn5.getRs().getString("date");
				mail_expediteur=conn5.getRs().getString("email_expediteur");
				messages.add(mail_expediteur+","+message+","+date);
			}
		} catch (SQLException e) {
			e.printStackTrace();
		}
		return messages;
	  }
	  
	  
	  /******** Main *********/
	  public static void main(String[] args) 
	  {	
			Serveur serv=new Serveur();
			try {
				serv.seConnecter();
			} catch (IOException e) {e.printStackTrace();}			
	  }//fin Main();

}//fin Classe Serveur
